package fudan.se.project.service.infrastructure.entity.conference.production;

import fudan.se.project.domain.User;
import fudan.se.project.domain.conference.Conference.ConferenceStage;
import fudan.se.project.domain.conference.production.ReviewInfo;
import fudan.se.project.repository.entity.conference.production.ReviewInfoRepository;
import fudan.se.project.service.infrastructure.base.IEntityService;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;

import static fudan.se.project.domain.conference.Conference.ConferenceStage.RESULT_RELEASE;
import static fudan.se.project.domain.conference.production.Paper.PaperState.COMPLETED;

@Service
public class ReviewInfoService implements IEntityService<ReviewInfo> {

    private final ReviewInfoRepository reviewInfoRepository;

    public ReviewInfoService(ReviewInfoRepository reviewInfoRepository) {
        this.reviewInfoRepository = reviewInfoRepository;
    }


    public List<ReviewInfo> findByAuthorUserAndPaperId(User userAuthor, long id) {
        return reviewInfoRepository.findByAuthorUserAndPaperId(userAuthor, id);
    }

    public ReviewInfo findByPaperId(User reviewer, long id) {
        return reviewInfoRepository.findByReviewerUserAndPaperId(reviewer, id);
    }

    public ReviewInfo updateVersion(ReviewInfo reviewInfo) {
        reviewInfo.setVersion(reviewInfo.getVersion() + 1);
        return reviewInfoRepository.save(reviewInfo);
    }

    public int numberOfReviewInfos(long conferenceId, int version) {
        return this.reviewInfoRepository.
                countDistinctByPaperConferenceIdAndVersion(conferenceId, version);
    }

    public int numberOfRebuttedReviewInfos(long conferenceId, int version) {
        return this.reviewInfoRepository.
                countDistinctByConferenceIdAnVersionInRebuttal(conferenceId, version);
    }

    public boolean isReviewInfoExistent(long id) {
        return null != this.reviewInfoRepository.findById(id);
    }

    public boolean isReviewInfoRevisable(ReviewInfo reviewInfo) {

        if (COMPLETED != reviewInfo.getPaper().getPaperState()) {
            return false;
        }

        final int version = reviewInfo.getVersion();
        final ConferenceStage stage = reviewInfo.getPaper().getConference().getStage();

        if (version == 0) {
            return stage.ordinal() < RESULT_RELEASE.ordinal();
        } else if (version == 1) {
            return stage == RESULT_RELEASE;
        } else {
            return false;
        }
    }

    @Override
    public ReviewInfo findById(long id) {
        return reviewInfoRepository.findById(id);
    }

    @Override
    public ReviewInfo save(ReviewInfo reviewInfo) {
        return this.reviewInfoRepository.save(reviewInfo);
    }

    @Override
    public Iterable<ReviewInfo> saveAll(Collection<ReviewInfo> reviewInfos) {
        return this.reviewInfoRepository.saveAll(reviewInfos);
    }
}
